iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0
AI Engineering

30天拆Agent:從Repo看設計系列 第 13 篇

Day 13|Tool 怎麼接進 Agent?從 `commerce-common` 到三種 Runtime

  • 分享至 

  • xImage
  •  

上一篇拆完 commerce-agents 的 Shopping Agent 後,這篇不再繼續拆每一個 Agent module,而是回答兩個問題:

Tool 定義好之後,怎麼真正掛到 Agent 上?

以及:

同一套 Shopping Agent,如何提供三種runtime的方式,跟claude溝通 Messages API、Agent SDK、Managed Agents?


1. commerce-common:Tool 的共用執行底座

有哪些 Shopping Tool,是由 Shopping Core 定義。

例如:

shopping-agent/core/shopping_agent/tools/registry.py

這裡定義了:

search_products
get_product_details

get_cart
add_to_cart

get_orders

search_policies
...

並依 ShoppingAgentConfig 決定這次 Deployment 真正開放哪些 Tool。

例如:

enable_cart = True

其中 Shopping Core 大致可以看成:

Shopping Core
│
├── tools/registry.py
│   └── Tool 名稱、description、input schema
│
├── gates.py
│   └── 寫入操作前的限制
│
└── executor.py
    └── Tool 最後對應哪個 Backend method

而 commerce-common 處理的是 Shopping Agent、Merchant Agent,以及不同 Runtime 都會重複遇到的共用問題:

commerce-common/commerce_common/
├── config.py
├── execution.py
├── fencing.py
├── memory.py
├── presentation.py
├── agent_sdk.py
└── mcp_server.py

官方 README 也把這一層定位成 config、fencing、memory、presentation、executor frame、events 等共用能力。


1-1. Tool 註冊,不代表 Tool 可以直接執行

例如 Model 想呼叫:

add_to_cart

整條路徑可以簡化成:

tools/registry.py
(shopping-agent/core/shopping_agent/tools/registry.py)
        │
        │ 這次 Agent 可以看到哪些 Tool
        ▼
commerce_common/execution.py
(shopping-agent/core/shopping_agent/executor.py)
        │
        │ 這個 Tool 是否允許被執行
        ▼
ShoppingToolExecutor
        │
        ▼
StorefrontBackend
(shopping-agent/core/shopping_agent/backend.py)
        │
        ▼
企業商品 / 購物車 / 訂單 API

這比只在 System Prompt 裡寫:

請不要呼叫沒有權限的工具。

可靠得多。


1-2. 換成 MCP,也沒有重新寫一套 Tool

到了 Agent SDK Runtime,原本的 Shopping Tool 仍然繼續使用。

Adapter 在:

shopping-agent/runtime-agent-sdk/
└── shopping_agent_sdk/
    └── shopping_tools.py

它做的事情是把 Shopping Core 已經定義好的 Tool contract,轉成 Agent SDK 可以使用的 MCP Tool。

所以:

Shopping Core Tool
        │
        ▼
Agent SDK Adapter
shopping_tools.py
        │
        ▼
MCP Tool
        │
        ▼
ShoppingToolExecutor
        │
        ▼
StorefrontBackend

這也是這個 Repo 很重要的一個設計:

Business Tool 定義一次,再由不同 Runtime Adapter 接出去。


1-3. 身份與 MCP 安全是分開處理的

這個 Repo 把安全拆成不同層:

User Identity
→ 這次是誰在操作?

Tool Permission
→ 這個 Agent 能不能呼叫這個 Tool?

MCP Exposure
→ 這台 MCP Server 能不能直接被外部連線?

其中 User Identity 與正式的 Authentication 的模組開發,主要仍然是 Host / Deployment 要負責。

User Identity:不要讓 Model 決定「我是誰」

以 Shopping Agent 為例,如果前端是 LINE:

LINE User
    ↓
FastAPI 驗證 LINE userId
    ↓
建立 Session
{
  session_id: "abc123",
  customer_id: "C001"
}
    ↓
後續請求只帶 session_id
    ↓
Backend 從 Session 取得 customer_id

這樣 Tool 就不需要接受:

get_orders(user_id="C001")

因為 user_id 如果是 Tool argument,就可能由 Model 產生或修改。

比較安全的做法是:

Host 先確認使用者身份,再把身份綁到 Session;Backend 只相信 Session 裡的身份。

Session 的參考實作可以看:

examples/demo_common/sessions.py
examples/demo_common/storefront.py

MCP Server Exposure:不要直接把 Tool Server 裸露出去

MCP Server 的共用安全檢查在:

commerce-common/commerce_common/mcp_server.py

Reference MCP Server 預設偏向只接受本機連線。

也就是開發環境比較接近:

Agent
  ↓
localhost MCP
  ↓
Backend

如果正式部署成 Remote MCP,不應只是把 Port 開到 Internet:

Internet
  ↓
MCP Server
  ↓
Backend

比較合理的架構是:

Internet
   ↓
Gateway
├─ Authentication
├─ Authorization
├─ Rate Limit
└─ Audit
   ↓
MCP Server
   ↓
Backend

所以 commerce-common/commerce_common/mcp_server.py 提供的比較像是:

避免 Reference MCP Server 不小心直接對外暴露的安全護欄。


2. 同一套 Shopping Core,三種 Runtime

三種 Runtime 是同一套:

Shopping Core
├── Config
├── Prompt
├── Skills
├── Tool Contracts
├── Gates
├── Executor
└── Backend

可以選擇三種執行方式:

                  Shopping Core
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
   Messages API    Agent SDK    Managed Agents

真正的差別只有一個核心問題:

誰負責 Agent Loop、Session、Tool Registration 和 Permission?

下面全部使用同一個案例。

使用者說:

我要找兩人用、8000 元以下的輕量帳篷。

Runtime 1|Messages API

Messages API 是三種做法裡,最接近一般 Backend Application 的方式。

主要程式位置:

shopping-agent/runtime-messages-api/
└── shopping_agent_runtime/
    └── orchestrator.py

Runtime 會建立一個 ShoppingAgent:

agent = ShoppingAgent(
    backend=my_backend,
    config=my_config,
    skills_dir=my_skills,
    memory_store=my_memory,
    client=anthropic_client,
)

這幾個主要參數分別對應:

參數 用途 主要程式位置
backend 商品、購物車、訂單真正去哪裡執行 shopping-agent/core/shopping_agent/backend.py
config Model、Brand、Cart、Orders 等能力設定 shopping-agent/core/shopping_agent/config.py
skills_dir Agent 工作 SOP shopping-agent/core/ 相關 Skill 載入邏輯
memory_store 長期記憶 commerce-common/commerce_common/memory.py
client Claude API Client runtime-messages-api/.../orchestrator.py

真正跑一輪時,再傳:

agent.stream_turn(
    messages,     # Conversation History
    session,      # 現在是哪個 User / Session
    state,        # 這個 Agent Session 已經做過哪些事情
)

這條路裡,Application 自己負責很多事情:

Webhook
Session
History
Agent Loop
Tool Dispatch
Streaming
Retry
Logging
UI

什麼時候適合?

如果公司本來已經有:

FastAPI
Redis
Database
Session Service
API Gateway

現在只是想:

在既有 Backend 裡加入一個 Agent。

那 Messages API 最直覺。

可以把它理解成:

我的 Application 本來就存在,Agent 只是其中一個能力。


Runtime 2|Agent SDK

第二種做法是 Agent SDK。

最大的差別是:

Agent Loop 不再自己寫。

主要組裝位置:

shopping-agent/runtime-agent-sdk/
└── shopping_agent_sdk/
    ├── agent.py
    └── shopping_tools.py

主要入口在:

shopping-agent/runtime-agent-sdk/
shopping_agent_sdk/agent.py

這裡透過 make_options() 組 Runtime:

options, toolset = make_options(
    backend=my_backend,
    config=my_config,
    session_id="user-123-session-1",
    user_id="user-123",
    max_turns=16,
    skills_dir=my_skills,
)

也就是:

Shopping Core
     │
     ▼
make_options()
     │
     ▼
ClaudeAgentOptions
     │
     ▼
Claude Agent SDK

Tool 怎麼接進來?

這裡最特別的是 MCP。

Adapter 在:

shopping-agent/runtime-agent-sdk/
└── shopping_agent_sdk/
    └── shopping_tools.py

原本 Shopping Core 的:

search_products

會被轉成 Agent SDK 看到的:

mcp__storefront__search_products

但這裡通常不是另外架一台遠端 MCP Server。

而是:

Claude Agent SDK
       │
       ▼
in-process MCP
       │
       ▼
ShoppingToolExecutor
       │
       ▼
StorefrontBackend

也就是 Tool 與 Agent 可以跑在同一個 Process 裡。


什麼時候適合?

如果想做的是:

一個 Container
=
一個能自己工作的 Agent Worker

例如:

Research Agent
Coding Agent
Operation Agent
Background Worker

Agent SDK 會比自己管理 Messages API Loop 更省事。

可以簡單區分成:

Messages API:把 Agent 放進既有 Application。

Agent SDK:Application 本身就是一個 Agent。


Runtime 3|Managed Agents

第三種做法再往前一步。

這次:

連 Agent Runtime 都不一定跑在自己的 Server。

Agent Definition 在:

shopping-agent/managed-agents/
└── shopping-agent/
    └── agent.yaml

原本 Python 裡面的:

Model
System Prompt
Skills
Tools

現在改成 Manifest:

agent.yaml
   │
   ├── Model
   ├── Prompt
   ├── Skills
   ├── MCP Server
   └── Tool Permission

這就是 Managed Agent 的 Agent Definition。


Tool 怎麼接?

這次 MCP 真的是 Remote MCP。

agent.yaml 裡會設定:

mcp_servers:
  - type: url
    name: storefront
    url: ${STOREFRONT_MCP_URL}

所以實際架構是:

Managed Agent
      │
      │ HTTPS / MCP
      ▼
Storefront MCP Server
      │
      ▼
ShoppingToolExecutor
      │
      ▼
StorefrontBackend
      │
      ▼
Company API

Tool Permission 也進 Manifest

例如:

search_products
→ always_allow

add_to_cart
→ always_ask

設定位置:

shopping-agent/managed-agents/
shopping-agent/agent.yaml

所以查商品可以直接執行:

search_products

但修改購物車:

add_to_cart

Runtime 可以先停下來要求確認。


什麼時候適合?

如果不想自己維護:

Agent Process
Agent Loop
Session Runtime
Tool Loop
Permission Pause

只想保留:

Company MCP
Business API
Credential
UI

那 Managed Agents 就比較接近平台化方案。


三種 Runtime 放在一起比較

Messages API Agent SDK Managed Agents
Agent Loop 自己管理 SDK 管 Platform 管
Agent 怎麼組 ShoppingAgent(...) ClaudeAgentOptions agent.yaml
Tool 接法 tools[] in-process MCP Remote MCP
Session Application 管 Application / SDK Platform Session
Backend Application Server Agent Process MCP Server 後方
Credential Application 管 Runtime Environment Vault / MCP
最適合 既有 Web / LINE Backend Container Agent / Worker Hosted Agent Platform

References


上一篇
Day 12|拆開 Claude Commerce Agents:一個 Agent 到底由哪些模組組成?
系列文
30天拆Agent:從Repo看設計 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言